<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace app\manage\controller\admin;

use app\common\model\MemberPluginOrder;
use buwang\base\AdminBaseController;
use buwang\service\PluginService;
use buwang\traits\Crud;
use think\facade\Cache;
use think\facade\View;

/**
 * 插件
 * @menu true
 * Class Plugin
 * @package app\manage\controller\admin
 */
class Plugin extends AdminBaseController
{
    use Crud;

    protected $model = null;//模型实例

    protected function initialize()
    {
        parent::initialize();
        $this->model = new \app\manage\model\admin\Plugin();
    }

    /**
     * 查看
     * @menu true
     */
    public function index()
    {
        if (request()->isAjax()) {
            //取得模块目录名称
            $dirs = array_map('basename', glob(ADDON_PATH . '*', GLOB_ONLYDIR));
            if ($dirs === false || !file_exists(ADDON_PATH)) return $this->error('插件目录不可读或者不存在');
            // 读取数据库插件表
            $addons = $this->model->order('id desc')->column('*', 'name');
            //TODO 清除插件列表缓存【后期加上清除插件缓存按钮】
            Cache::has('addonslist') && Cache::delete('addonslist');
            $dir_addons_list = get_addons_list();
            //遍历插件列表
            foreach ($dirs as $name) {
                //如果没有安装过
                if (!isset($addons[$name]) && isset($dir_addons_list[$name])) {
                    $addons[$name] = $dir_addons_list[$name];
                    if ($addons[$name]) {
                        $addons[$name]['status'] = -1;
                        $addons[$name]['create_time'] = 0;
                        $addons[$name]['update_time'] = 0;
                    }
                }
                switch ($addons[$name]['type']){
                    case 'admin_system':
                        $addons[$name]['type_text']="运营平台插件";
                        break;
                    case 'member_system':
                        $addons[$name]['type_text']="租户平台插件";
                        break;
                    case 'all_system':
                        $addons[$name]['type_text']="运营平台及租户平台插件";
                        break;
                    default:
                        [$scope,$ext_name] = explode('_',$addons[$name]['type']);
                        $addons[$name]['type_text']="租户应用{$ext_name}插件";
                        break;
                }
            }
            return $this->success(['list' => $addons, 'total' => sizeof($addons)]);
        }
        $this->layout && $this->app->view->engine()->layout($this->layout);
        return view();
    }
    public function tenantList(){
        //联表查询
        $this->relationSearch=true;
        if ($this->request->isAjax()) {
            if (input('selectFieds')) {
                return $this->selectList();
            }
            $this->model=new Member();
            list($page, $limit, $where) = $this->buildTableParames();
            $this->model=new MemberPluginOrder();
            $count = $this->model
                ->with(['member','plugin'])
                ->where($where)
                ->count();
            $list = $this->model
                ->with(['member','plugin'])
                ->where($where)
                ->page($page, $limit)
                ->order($this->sort)
                ->select();
            $data = [
                'total' => $count,
                'list' => $list,
            ];
            return $this->success('success', $data);
        }
        return view();
    }
    /**
     * 构建请求参数
     * @param array $excludeFields 忽略构建搜索的字段
     * @return array
     */
    protected function buildTableParames($excludeFields = [])
    {
        $get = $this->request->get('', null, null);
        $page = isset($get['page']) && !empty($get['page']) ? $get['page'] : 1;
        $limit = isset($get['limit']) && !empty($get['limit']) ? $get['limit'] : 15;
        $filters = isset($get['filter']) && !empty($get['filter']) ? $get['filter'] : '{}';
        $ops = isset($get['op']) && !empty($get['op']) ? $get['op'] : '{}';
        // json转数组
        $filters = json_decode($filters, true);
        $ops = json_decode($ops, true);
        $where = [];
        $excludes = [];

        // 判断是否关联查询
        $tableName = $this->getTableName();
        foreach ($filters as $key => $val) {
            if (in_array($key, $excludeFields)) {
                $excludes[$key] = $val;
                continue;
            }
            if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $key)) {
                continue;
            }
            $op = strtoupper(isset($ops[$key]) && !empty($ops[$key]) ? $ops[$key] : '%*%');
            if (!empty($this->model) && $this->relationSearch && count(explode('.', $key)) == 2) {
                $key = "{$key}";
            }
            switch ($op) {
                case '=':
                    $where[] = [$key, '=', $val];
                    break;
                case 'LIKE':
                case '%*%':
                    $where[] = [$key, 'LIKE', "%{$val}%"];
                    break;
                case '*%':
                    $where[] = [$key, 'LIKE', "{$val}%"];
                    break;
                case '%*':
                    $where[] = [$key, 'LIKE', "%{$val}"];
                    break;
                case 'RANGE':
                    if(!is_string($val)){
                        continue 2;
                    }
                    [$beginTime, $endTime] = explode(' - ', $val);
                    $where[] = [$key, '>=', strtotime($beginTime)];
                    $where[] = [$key, '<=', strtotime($endTime)];
                    break;
                case 'BETWEEN':
                case 'NOT BETWEEN'://TODO 修复完善范围查询条件
                    $arr = array_slice(explode(',', $val), 0, 2);
                    if (stripos($val, ',') === false || !array_filter($arr, function ($v) {
                            return $v != '' && $v !== false && $v !== null;
                        })) {
                        continue 2;
                    }
                    //当出现一边为空时改变操作符
                    if ($arr[0] === '') {
                        $op = $op == 'BETWEEN' ? '<=' : '>';
                        $arr = $arr[1];
                    } elseif ($arr[1] === '') {
                        $op = $op == 'BETWEEN' ? '>=' : '<';
                        $arr = $arr[0];
                    }
                    $where[] = [$key, $op, $arr];
                    break;
                case 'IN': //增加in类型查询
                case 'NOT IN':
                    $where[] = [$key, $op, is_array($val) ? $val : explode(',', $val)];
                    break;
                default:
                    $where[] = [$key, $op, "%{$val}"];
            }
        }
        return [$page, $limit, $where, $excludes];
    }

    /**
     * 安装
     * @param $name
     * @return \think\Response
     */
    public function install($name = null)
    {
        if (request()->isAjax()) {
            $name = $name ? $name : request()->post("name/s");
            if (!$name) return $this->error('插件名有误');

            $this->model->startTrans();
            try {
                PluginService::install($name);

                $this->model->commit();
            } catch (\Exception $e) {
                $this->model->rollback();
                return $this->error($e->getMessage());
            }
            return $this->success();
        }
        return $this->error("请求方法错误");
    }

    /**
     * 卸载
     * @param $name
     * @return \think\Response
     */
    public function uninstall($name = null)
    {
        if (request()->isAjax()) {
            $name = $name ? $name : request()->post("name/s");
            if (!$name) return $this->error('插件名有误');

            $this->model->startTrans();
            try {
                PluginService::uninstall($name,true);

                $this->model->commit();
            } catch (\Exception $e) {
                $this->model->rollback();
                return $this->error($e->getMessage());
            }
            return $this->success();
        }
        return $this->error("请求方法错误");
    }

    /**
     * 启用
     * @param $name
     * @return \think\Response
     */
    public function enable($name = null)
    {
        if (request()->isAjax()) {
            $name = $name ? $name : request()->post("name/s");
            if (!$name) return $this->error('插件名有误');

            $this->model->startTrans();
            try {
                PluginService::enable($name);

                $this->model->commit();
            } catch (\Exception $e) {
                $this->model->rollback();
                return $this->error($e->getMessage());
            }
            return $this->success();
        }
        return $this->error("请求方法错误");
    }

    /**
     * 禁用
     * @param $name
     * @return \think\Response
     */
    public function disable($name = null)
    {
        if (request()->isAjax()) {
            $name = $name ? $name : request()->post("name/s");
            if (!$name) return $this->error('插件名有误');

            $this->model->startTrans();
            try {
                PluginService::disable($name);

                $this->model->commit();
            } catch (\Exception $e) {
                $this->model->rollback();
                return $this->error($e->getMessage());
            }
            return $this->success();
        }
        return $this->error("请求方法错误");
    }

    /**
     * 设置插件页面
     * @param null $name
     * @return \think\Response|\think\response\View
     */
    public function config($name = null)
    {
        $name = $name ? $name : request()->request("name/s");
        if (!$name) return $this->error('插件名有误');
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $name)) return $this->error('插件名称不正确！');
        if (!is_dir(ADDON_PATH . $name)) return $this->error('目录不存在！');
        $info = get_addons_info($name);
        $config = get_addons_config($name);
        if (!$info) return $this->error('配置不存在！');
        //var_dump($config);die;
        if (request()->isPost()) {
            $params = request()->post();
            if ($params) {
                foreach ($config as $k => &$v) {
                    if (isset($params[$v['name']])) {
                        //TODO to be completed
                        if ($v['type'] == 'array') {
                            $params[$v['name']] = is_array($params[$v['name']]) ? $params[$v['name']] : (array)json_decode($params[$v['name']], true);
                            $value = $params[$v['name']];
                        } else {
                            $value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']];
                        }
                        $v['value'] = $value;
                    }
                }
                try {
                    //更新配置文件
                    set_addons_fullconfig($name, $config);
                    PluginService::refresh();
                } catch (\Exception $e) {
                    return $this->error($e->getMessage());
                }
            }
            return $this->success('插件配置保存成功！');
        }
        //兼容处理前后端分离
        if ($this->request->isAjax()) {
            return $this->success('success', ['info' => $info, 'config' => $config]);
        } else {
            $this->layout && $this->app->view->engine()->layout($this->layout);
            View::assign('addon', ['info' => $info, 'config' => $config]);
            $configFile = ADDON_PATH . $name . DS . 'config.html';
            $viewFile = is_file($configFile) ? $configFile : '';
            return view($viewFile);
        }
    }
}
